﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AUtil
{
    public sealed class ImageUtils
    {

        public enum Mode
        {
            默认,
            反向
        }

        // 用于转换的字符串
        public static string chars = "#M1V*;:,._ ";

        // 转换的字符
        private static char[,] tempChar = null;

        /// <summary>
        /// 保存字符画
        /// </summary>
        /// <param name="outFilePath"></param>
        public static void Save(string outFilePath)
        {
            if (tempChar != null)
            {
                string str = ToString(tempChar);
                using (StreamWriter sw = new StreamWriter(new FileStream(outFilePath, FileMode.Create)))
                {
                    sw.Write(str);
                }
            }
        }

        // 转换为string
        public static string ToString(char[,] temp)
        {
            StringBuilder builder = new StringBuilder();

            for (int y = 0; y < temp.GetLength(1); y++)
            {
                for (int x = 0; x < temp.GetLength(0); x++)
                {
                    builder.Append(temp[x, y]);
                }
                builder.AppendLine();
            }

            return builder.ToString();
        }


        private static string Reverse()
        {
            IEnumerable<char> temp = chars.Reverse<char>();
            return new string(temp.ToArray());
        }

        public static void Convert(string imgPath, Mode mode)
        {
            string str = chars;
            if (mode == Mode.反向)
            {
                str = Reverse();
            }

            ImageToChars(imgPath, str);
            string savePath = Path.GetDirectoryName(imgPath);
            Save(savePath + "/" + Path.GetFileNameWithoutExtension(imgPath) + ".txt");
        }

        public static void Convert(string imgPath, string outFileName,Mode mode)
        {
            string str = chars;
            if (mode == Mode.反向)
            {
                str = Reverse();
            }
            ImageToChars(imgPath, str);
            Save(outFileName);
        }

        /// <summary>
        /// 转换图片到字符序列
        /// </summary>
        /// <param name="imgPath"></param>
        /// <returns></returns>
        public static char[,] ImageToChars(string imgPath,string str)
        {
            Image img = Image.FromFile(imgPath);

            Bitmap bitmap = new Bitmap(img);

            tempChar = new char[bitmap.Width, bitmap.Height];

            // 横向遍历 x变
            for (int y = 0; y < bitmap.Height; y++)
            {
                for (int x = 0; x < bitmap.Width; x++)
                {
                    // 获取像素点的颜色
                    Color color = bitmap.GetPixel(x,y);
                    // 灰度值
                    int v = ToGray(color);

                    // 根据灰度转换为对应的字符
                    tempChar[x, y] = ColorToChar(Color.FromArgb(v, v, v), str);
                }
            }
            return tempChar;
        }

        /// <summary>
        /// 到灰阶
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        public static int ToGray(Color color)
        {
            return (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
        }

        /// <summary>
        /// 根据灰阶转换字符
        /// </summary>
        /// <param name="color"></param>
        /// <returns></returns>
        public static char ColorToChar(Color color,string str)
        {
            int b = color.B;

            char c = ' ';

            if (b > 235)
                c = str[str.Length - 1];
            else if (b > 215)
                c = str[str.Length - 2];
            else if (b > 195)
                c = str[str.Length - 3];
            else if (b > 175)
                c = str[str.Length - 4];
            else if (b > 155)
                c = str[str.Length - 5];
            else if (b > 135)
                c = str[str.Length - 6];
            else if (b > 115)
                c = str[str.Length - 7];
            else if (b > 95)
                c = str[str.Length - 8];
            else if (b > 75)
                c = str[str.Length - 9];
            else if (b > 55)
                c = str[str.Length - 10];
            else if (b > 35)
                c = str[str.Length - 11];
            return c;
        }

    }
}
